package org.example.advice;

import lombok.extern.slf4j.Slf4j;
import org.example.annotation.Encryption;
import org.example.util.EncryptUtil;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Objects;

/**
 * 一个实现ResponseBodyAdvice接口的类，用于对响应体进行加密处理。
 *
 * @author WN
 * @date：2024/03/25 15:57
 */
@ControllerAdvice
@Slf4j
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice {

    /**
     * 判断当前方法的返回值是否需要进行加密处理。
     *
     * @param returnType 方法返回类型
     * @param converterType 转换器类型
     * @return 如果方法返回类型上标注了Encryption注解，则返回true，表示需要加密；否则返回false。
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return returnType.hasMethodAnnotation(Encryption.class);
    }

    /**
     * 在响应体写入之前对响应体进行加密处理。
     *
     * @param body 响应体内容
     * @param returnType 方法返回类型
     * @param selectedContentType 选中的内容类型
     * @param selectedConverterType 选中的转换器类型
     * @param request 请求对象
     * @param response 响应对象
     * @return 返回加密后的响应体内容。
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (Objects.isNull(body)){
            return null;
        }
        log.info("加密前：{}", body);
        String s = EncryptUtil.Base64Encode(body.toString());
        log.info("加密后：{}", s);
        log.info("解密后：{}", EncryptUtil.Base64Decode(s));
        return s;
    }
}
